package com.zenithmind.disk.feign;

import com.zenithmind.disk.pojo.vo.UsersVO;
import com.zenithmind.common.result.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;

/**
 * 用户服务远程调用接口
 * 遵循接口隔离原则：只定义网盘服务需要的用户操作
 * 遵循依赖倒置原则：依赖抽象接口而非具体实现
 * 遵循单一职责原则：专注于用户相关的远程调用
 */
@FeignClient(
    name = "user-service",
    path = "/api/zenithMind/user",
    fallback = UserFeignFallbackImpl.class,
    contextId = "userFeignClient"
)
public interface UserFeignClient {

    /**
     * 根据ID获取用户信息
     * 用于验证用户存在性和获取用户存储配额信息
     *
     * @param userId 用户ID，不能为空
     * @return 用户信息结果
     * @apiNote 对应用户服务的 GET /api/zenithMind/user/getUserById?userId={userId}
     */
    @GetMapping("/getUserById")
    Result<UsersVO> getUserById(@RequestParam("userId") @NotBlank String userId);

    /**
     * 更新用户已用存储空间
     * 用于文件上传、删除时同步更新用户的存储使用量
     *
     * @param userId 用户ID，不能为空
     * @param fileSize 文件大小变化量（字节），正数表示增加，负数表示减少
     * @return 更新结果
     * @apiNote 对应用户服务的 PUT /api/zenithMind/user/updateStorageUsed?userId={userId}&fileSize={fileSize}
     */
    @PutMapping("/updateStorageUsed")
    Result<Void> updateStorageUsed(
        @RequestParam("userId") @NotBlank String userId,
        @RequestParam("fileSize") long fileSize
    );

    /**
     * 检查用户存储空间是否充足
     * 用于文件上传前的预检查
     *
     * @param userId 用户ID，不能为空
     * @param requiredSize 需要的存储空间大小（字节），必须大于0
     * @return 检查结果，true表示空间充足
     * @apiNote 对应用户服务的 GET /api/zenithMind/user/checkStorageSpace?userId={userId}&requiredSize={requiredSize}
     */
    @GetMapping("/checkStorageSpace")
    Result<Boolean> checkStorageSpace(
        @RequestParam("userId") @NotBlank String userId,
        @RequestParam("requiredSize") @Min(1) long requiredSize
    );

    /**
     * 获取用户存储统计信息
     * 用于显示用户的存储使用情况
     *
     * @param userId 用户ID，不能为空
     * @return 存储统计信息
     * @apiNote 对应用户服务的 GET /api/zenithMind/user/getStorageStats?userId={userId}
     */
    @GetMapping("/getStorageStats")
    Result<StorageStatsVO> getStorageStats(@RequestParam("userId") @NotBlank String userId);

    /**
     * 存储统计信息VO
     * 遵循单一职责原则：专门用于存储统计数据传输
     */
    class StorageStatsVO {
        /** 总存储限制（字节） */
        private Long storageLimit;
        /** 已使用存储（字节） */
        private Long storageUsed;
        /** 剩余存储（字节） */
        private Long storageRemaining;
        /** 使用率（百分比） */
        private Double usagePercentage;

        // 构造函数
        public StorageStatsVO() {}

        public StorageStatsVO(Long storageLimit, Long storageUsed) {
            this.storageLimit = storageLimit;
            this.storageUsed = storageUsed;
            this.storageRemaining = storageLimit - storageUsed;
            this.usagePercentage = storageLimit > 0 ? (double) storageUsed / storageLimit * 100 : 0.0;
        }

        // Getter和Setter方法
        public Long getStorageLimit() { return storageLimit; }
        public void setStorageLimit(Long storageLimit) { this.storageLimit = storageLimit; }

        public Long getStorageUsed() { return storageUsed; }
        public void setStorageUsed(Long storageUsed) { this.storageUsed = storageUsed; }

        public Long getStorageRemaining() { return storageRemaining; }
        public void setStorageRemaining(Long storageRemaining) { this.storageRemaining = storageRemaining; }

        public Double getUsagePercentage() { return usagePercentage; }
        public void setUsagePercentage(Double usagePercentage) { this.usagePercentage = usagePercentage; }

        /**
         * 检查存储空间是否充足
         * @param requiredSize 需要的空间大小
         * @return true如果空间充足
         */
        public boolean hasEnoughSpace(long requiredSize) {
            return storageRemaining != null && storageRemaining >= requiredSize;
        }

        /**
         * 检查存储空间是否即将用完（使用率超过90%）
         * @return true如果即将用完
         */
        public boolean isAlmostFull() {
            return usagePercentage != null && usagePercentage >= 90.0;
        }
    }
}